﻿using Infrastructure;
using OpenAuth.App.Interface;
using OpenAuth.App.Request;
using OpenAuth.App.Response;
using OpenAuth.Repository.Domain;
using OpenAuth.Repository.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;

namespace OpenAuth.App.Report
{
    public class InspectPlanReport : BaseApp<InspectPlan>
    {
        private IAuth _auth;
        public InspectPlanReport(IUnitWork unitWork, IRepository<InspectPlan> repository, RevelanceManagerApp app, IAuth auth) : base(unitWork, repository)
        {
            _auth = auth;
        }

        public List<InspectPlanReportResp> LoadData(InspectPlanReportReq req)
        {
            var loginContext = _auth.GetCurrentUser();
            if (loginContext == null)
            {
                throw new CommonException("登录已过期", Define.INVALID_TOKEN);
            }
            //默认查昨天一天
            req.StartTime = req.StartTime?.ToString("yyyy-MM-dd 00:00:00").ToDateTime() ??
                            DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd 00:00:00").ToDateTime();
            req.EndTime = req.EndTime?.AddDays(1).ToString("yyyy-MM-dd 00:00:00").ToDateTime() ??
                          DateTime.Now.ToString("yyyy-MM-dd 00:00:00").ToDateTime();
            req.EndTime = req.EndTime?.AddMilliseconds(1);
            List<string> orgIdList = new List<string>();
            if (!string.IsNullOrWhiteSpace(req.OrgId))
            {
                var org = loginContext.Orgs.SingleOrDefault(u => u.Id == req.OrgId);
                foreach (Org item in loginContext.Orgs)
                {
                    if (item.CascadeId.Contains(org.CascadeId))
                    {
                        orgIdList.Add(item.Id);
                    }
                }
            }
            else
            {
                orgIdList = loginContext.Orgs.Select(u => u.Id).ToList();
            }

            var plans = UnitWork.Find<InspectPlan>(u => orgIdList.Contains(u.OrgId)).ToList();
            var schedules = UnitWork.Find<InspectSchedule>(u => u.StartTime >= req.StartTime && u.EndTime < req.EndTime).ToList();
            if (plans.Count == 0 || schedules.Count == 0)
                throw new Exception("没有符合条件的数据!");
            var scheduleIdList = schedules.Select(s => s.Id).ToList();
            var records = UnitWork.Find<InspectRecord>(u => scheduleIdList.Contains(u.InspectScheduleId)).ToList();
            var recordItems = records.Count == 0 ? null
                : UnitWork.Find<InspectRecordItem>(u => records.Select(r => r.Id).Contains(u.InspectRecordId)).ToList();

            //var overTimeInspect = UnitWork.Find<InspectViolation>(u => u.Category == 1 && u.CreateTime >= req.startTime
            //    && u.CreateTime < req.endTime).ToList();
            var inspectContentList = UnitWork.Find<InspectPlanContent>(null).ToList();

            List<InspectPlanReportResp> result = new List<InspectPlanReportResp>();
            foreach (var plan in plans)
            {
                var planContentCount = inspectContentList.Where(u => u.InspectPlanId == plan.Id)
                    .Select(u => u.InspectAreaId).Distinct().Count();
                //var all = schdules.Where(u => u.InspectPlanId == plan.Id).Count();
                //var yxClass = schdules.Where(u => u.InspectPlanId == plan.Id && u.IsInspection == true);
                //var done = yxClass.Count();
                //var violationClassIds = overTimeInspect.Select(u => u.InspectScheduleId);
                //var overTimeCount = violationClassIds.Intersect(yxClass.Select(u => u.Id)).Count();
                //var resp = new InspectPlanReportResp()
                //{
                //    planId = plan.Id,
                //    planName = plan.Name,
                //    All = all,
                //    Done = done,
                //    NotInspect = all - done,
                //    OverTime = overTimeCount,
                //    percentage = all == 0 ? 0 : Math.Round((Convert.ToDecimal(done) / all * 100), 1)
                //};
                var allA = schedules.Count(u => u.InspectPlanId == plan.Id) * planContentCount;
                var doneA = 0;
                var overTimeCountA = 0;
                var planRecords = records.Where(u => u.InspectPlanId == plan.Id);
                if (planRecords.Any() && recordItems != null)
                {
                    var index = 0;
                    var index2 = 0;
                    foreach (var r in planRecords)
                    {
                        var items = recordItems.Where(u => u.InspectRecordId == r.Id);
                        if (items.Any())
                        {
                            index += items.Select(u => u.InspectAreaId).Distinct().Count();
                            var temp = items.Where(u => u.IsOverTime == true);
                            if (temp.Any())
                            {
                                index2 += temp.Select(u => u.InspectAreaId).Distinct().Count();
                            }
                        }
                    }
                    doneA = index;
                    overTimeCountA = index2;
                }
                if (doneA > allA)
                    doneA = allA;
                var resp = new InspectPlanReportResp()
                {
                    PlanId = plan.Id,
                    PlanName = plan.Name,
                    //All = all,
                    //Done = done,
                    //NotInspect = all - done,
                    //OverTime = overTimeCount,
                    //percentage = all == 0 ? 0 : Math.Round((Convert.ToDecimal(done) / all * 100), 1)
                    AllArea = allA,
                    DoneArea = doneA,
                    NiArea = allA - doneA,
                    OtArea = overTimeCountA,
                    PercentageArea = allA == 0 ? 0 : Math.Round((Convert.ToDecimal(doneA) / allA * 100), 1)
                };
                result.Add(resp);
            }
            return result;
        }

        public TableData GetReportDetailList(InspectPlanReportReq req)
        {
            var loginContext = _auth.GetCurrentUser();
            if (loginContext == null)
            {
                throw new CommonException("登录已过期", Define.INVALID_TOKEN);
            }
            //默认查昨天一天
            req.StartTime = req.StartTime?.ToString("yyyy-MM-dd 00:00:00").ToDateTime() ??
                            DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd 00:00:00").ToDateTime();
            req.EndTime = req.EndTime?.AddDays(1).ToString("yyyy-MM-dd 00:00:00").ToDateTime() ??
                          DateTime.Now.ToString("yyyy-MM-dd 00:00:00").ToDateTime();
            req.EndTime = req.EndTime?.AddMilliseconds(1);
            List<string> orgIdList = new List<string>();
            if (!string.IsNullOrWhiteSpace(req.OrgId))
            {
                var org = loginContext.Orgs.SingleOrDefault(u => u.Id == req.OrgId);
                foreach (Org item in loginContext.Orgs)
                {
                    if (item.CascadeId.Contains(org.CascadeId))
                    {
                        orgIdList.Add(item.Id);
                    }
                }
            }
            else
            {
                orgIdList = loginContext.Orgs.Select(u => u.Id).ToList();
            }

            Expression<Func<InspectViolation, bool>> violationExpression = PredicateBuilder.True<InspectViolation>();
            violationExpression = violationExpression.And(u => orgIdList.Contains(u.OrgId))
                .And(u => u.InspectPlanId == req.PlanId).And(u => u.CreateTime >= req.StartTime)
                .And(u => u.CreateTime < req.EndTime);
            violationExpression = req.Category == 0
                ? violationExpression.And(u => u.Category == 0 || u.Category == 2)
                : violationExpression.And(u => u.Category == req.Category);
            var result = new TableData();
            var dataList = new List<InspectViolationList>();
            var violationList = UnitWork.Find(violationExpression);

            var data = violationList.Include(u => u.InspectPlan)
                .Include(u => u.Org).Include(u => u.InspectSchedule)
                .OrderByDescending(u => u.CreateTime).ToList();
            var userList = UnitWork.Find<User>(null).ToList();
            foreach (var item in data)
            {
                var obj = new InspectViolationList
                {
                    Id = item.Id,
                    PlanName = item.InspectPlan?.Name,
                    OrgName = item.Org.Name,
                    Reason = item.Reason,
                    AuditMind = item.AuditMind,
                    IsViolation = item.IsViolation,
                    Status = item.Status,
                    Category = item.Category
                };
                if (item.InspectSchedule != null)
                {
                    string className;
                    if (string.IsNullOrEmpty(item.InspectSchedule.ShiftTeam))
                    {
                        className = item.InspectSchedule.ClassName;
                    }
                    else
                    {
                        var startTime = item.InspectSchedule.StartTime;
                        var endTime = item.InspectSchedule.EndTime;
                        className = startTime.ToShortDateString() == endTime.ToShortDateString()
                            ? $"{item.InspectSchedule.ClassName}({startTime:yyyy-MM-dd HH:mm}至{endTime:HH:mm})"
                            : $"{item.InspectSchedule.ClassName}({startTime:yyyy-MM-dd HH:mm}至{endTime:yyyy-MM-dd HH:mm})";
                    }
                    obj.ClassName = className;
                    string userNames;
                    if (string.IsNullOrEmpty(item.InspectSchedule.ShiftTeam))
                    {
                        string[] ids = item.InspectSchedule.Executor.Split("，");
                        var users = userList.Where(u => ids.Contains(u.Id)).Select(u => u.Name);
                        userNames = string.Join(",", users);
                    }
                    else
                    {
                        var users = userList.Where(u => u.InspectTeam == item.InspectSchedule.ShiftTeam).Select(u => u.Name);
                        userNames = string.Join(",", users);
                    }
                    obj.Person = userNames;
                }

                dataList.Add(obj);
            }
            result.data = dataList;
            result.count = violationList.Count();
            return result;
        }
    }
}
